/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package researchgrants.parts.LoggedData.panels.trees;

import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;

/**
 * Defines the behavior of a node in a tree.
 * It is a template so that a single TreeNode wraps a single K element.
 * The class implement functions to create the tree structure and functions to retreive and navigate through the tree.
 * By referencing a TreeNode, one can navigate throughout the tree, using getParent() and getSons()
 * @author DOStudent1
 */
public class TreeNode<K> {

    // the wrapped element
    private K value;
    // the list of sons
    // should be empty when no sons are linked.
    private Collection<TreeNode<K>> sonsNodes=new LinkedList<TreeNode<K>>();
    // a reference to the parent
    // should be null if no parent is linked, for the head of a tree.
    private TreeNode<K> parent=null;

    // initialize a TreeNode, while being provided with a wrapped element
    // This new TreeNode is initiated as a single-element tree. To extend the tree, you should call addSon with another created TreeNode. This can be done recursively.
    public TreeNode (K value) {
        this.value=value;
    }
    
    // retrieves the wrapped value
    public K getValue() {
        return(value);
    }
    
    // links another TreeNode below this TreeNode
    public void addSon(TreeNode<K> sonNode) {
        if (sonNode.parent!=null) {
            throw new RuntimeException("This node is already linked.");
        }
        sonNode.parent=this;
        sonsNodes.add(sonNode);
    }
    
    // unlinks a son of this TreeNode.
    // The son can then be relinked to a different location within the tree.
    public boolean removeSon(TreeNode<K> son) {
        boolean removedAlready=false;
        for (Iterator<TreeNode<K>> it = sonsNodes.iterator(); it.hasNext() && !removedAlready;) {
            TreeNode<K> treeNode = it.next();
            if (treeNode.equals(son)) {
                son.parent=null;
                it.remove();
                removedAlready=true;
            }
        }
        return(removedAlready);
    }
    
    // Retreives a copy of the list of sons
    public Collection<TreeNode<K>> sonsNodeCollection() {
        Collection<TreeNode<K>> sons=new LinkedList<TreeNode<K>>();
        for (Iterator<TreeNode<K>> it = sonsNodes.iterator(); it.hasNext();) {
            TreeNode<K> treeNode = it.next();
            sons.add(treeNode);
        }
        return(sons);
    }
    
    // query about a parent
    public boolean hasParent() {
        return(parent!=null);
    }
    
    // retreive the parent
    public TreeNode<K> getParent() {
        return(parent);
    }
    
}
